package com.hse.virtualnetwork;

import com.hse.network.ICoordinator;
import com.hse.network.ICoordinatorClient;
import com.hse.network.IEndDevice;
import com.hse.network.exceptions.NetworkException;
import org.junit.After;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;

/**
 * Created by IntelliJ IDEA.
 * User: Lexa
 * Date: May 31, 2009
 * Time: 7:20:03 PM
 * To change this template use File | Settings | File Templates.
 */
public class VirtualCoordinatorEndDeviceTester {
    private final static Short PORT_NUMBER_1 = 21212;
    private final static Short PORT_NUMBER_2 = 31217;
    private ICoordinator coordinator;
    private IEndDevice endDevice;

    @Before
    public void init() throws InstantiationException {
        coordinator = new VirtualCoordinator();
        endDevice = new VirtualEndDevice();
    }

    @After
    public void delete() {
        coordinator.close();
        endDevice.close();
    }

    @Test(timeout = 3000)
    public void createNetworkConnectEndDevice() throws NetworkException, InstantiationException {
        coordinator.createNetwork(PORT_NUMBER_1);
        endDevice.connect(PORT_NUMBER_2);
        final ICoordinatorClient client = coordinator.accept();
        Assert.assertNotNull(client);
    }

    @Test(timeout = 3000)
    public void sendRecv() throws NetworkException {
        coordinator.createNetwork(PORT_NUMBER_1);
        endDevice.connect(PORT_NUMBER_2);
        final ICoordinatorClient client = coordinator.accept();

        final byte[] sendData = "Hello World!".getBytes();
        endDevice.send(sendData);
        byte[] recvData = client.recv();
        Assert.assertArrayEquals(sendData, recvData);

        client.send(sendData);
        recvData = endDevice.recv();
        Assert.assertArrayEquals(sendData, recvData);
    }

    @Test(timeout = 3000)
    public void canRead() throws NetworkException, InterruptedException {
        coordinator.createNetwork(PORT_NUMBER_1);
        endDevice.connect(PORT_NUMBER_2);
        final ICoordinatorClient client = coordinator.accept();

        final byte[] sendData = "Hello World!".getBytes();

        Assert.assertFalse(client.canRead());
        endDevice.send(sendData);
        Thread.sleep(5);
        Assert.assertTrue(client.canRead());
        client.recv();
        Thread.sleep(5);
        Assert.assertFalse(client.canRead());

        Assert.assertFalse(endDevice.canRead());
        client.send(sendData);
        Thread.sleep(5);
        Assert.assertTrue(endDevice.canRead());
        endDevice.recv();
        Thread.sleep(5);
        Assert.assertFalse(endDevice.canRead());
    }

    @Test(timeout = 3000)
    public void canAccept() throws NetworkException, InterruptedException {
        coordinator.createNetwork(PORT_NUMBER_1);
        Assert.assertFalse(coordinator.canAccept());
        endDevice.connect(PORT_NUMBER_2);
        Thread.sleep(5);
        Assert.assertTrue(coordinator.canAccept());
        coordinator.accept();
        Assert.assertFalse(coordinator.canAccept());
    }

    @Test
    public void multipleJoin() throws NetworkException {
        coordinator.createNetwork(PORT_NUMBER_1);
        endDevice.connect(PORT_NUMBER_2);
        final ICoordinatorClient client = coordinator.accept();
        Assert.assertNotNull(client);

        VirtualEndDevice secondEndDevice = new VirtualEndDevice();
        secondEndDevice.connect(PORT_NUMBER_2);
        final ICoordinatorClient secondClient = coordinator.accept();
        Assert.assertNotNull(secondClient);
    }

    @Test
    public void multipleSend() throws NetworkException {
        coordinator.createNetwork(PORT_NUMBER_1);
        endDevice.connect(PORT_NUMBER_2);
        final ICoordinatorClient client = coordinator.accept();
        Assert.assertNotNull(client);

        VirtualEndDevice secondEndDevice = new VirtualEndDevice();
        secondEndDevice.connect(PORT_NUMBER_2);
        final ICoordinatorClient secondClient = coordinator.accept();
        Assert.assertNotNull(secondClient);

        final byte[] sendData = "Hello World!".getBytes();
        endDevice.send(sendData);
        byte[] recvData = client.recv();
        Assert.assertArrayEquals(sendData, recvData);

        client.send(sendData);
        recvData = endDevice.recv();
        Assert.assertArrayEquals(sendData, recvData);

        secondEndDevice.send(sendData);
        recvData = secondClient.recv();
        Assert.assertArrayEquals(sendData, recvData);

        secondClient.send(sendData);
        recvData = secondEndDevice.recv();
        Assert.assertArrayEquals(sendData, recvData);

    }
}
